#include "TransformTool.h"
#include <QPainter>
#include <math.h>



TransformTool::TransformTool (QWidget * parent)
: AbstractTool (parent), _isTransformStart (false), 
  _isTranslateStart (false), _isRotateStart (false), _isScaleStart (false)
{
  setText (tr ("Transform"));
}



TransformTool::~TransformTool ()
{
}



void TransformTool::_startTransform ()
{
  _isTransformStart = true;
  _pAction = new TransformAction (__pWork);
  __pWork->getDoc ()->openPreview (_pAction.cvt< AbstractAction > ());
  _pAction->handleStartEvent ();
  _curControlBox = _pAction->getCurTransSel ()->getBounding ();
  _origControlBox = _curControlBox;
}



void TransformTool::_finishTransform ()
{
  _isTransformStart = false;
//   Ptr< QImage > pResultImage = new QImage (*__pDoc->getCurrentLayer ()
//     ->getImage ());
//   QRect imageRegion = __pDoc->getCurrentLayer ()
//     ->getImage ()->rect ();
//   _transform (pResultImage, imageRegion);
//   __pDoc->getCurrentLayer ()->setImage (pResultImage);
//   __pDoc->getCurrentLayer ()->closePreview ();
}



void TransformTool::_cancelTransform ()
{
  _isTransformStart = false;
//   (*_pCurSelection) = _origSelection;
//   __pDoc->getCurrentLayer ()->closePreview ();
}



void TransformTool::_transformControlBox ()
{
  QMatrix3x3 & transformMatrix = _pAction->getTrans ().transformMatrix;

  // Transform control box
  for (int i = 0; i < _origControlBox.size (); ++i)
  {
    QPointF newPoint = TransformHelper::transform (
      _origControlBox.point (i), transformMatrix);
    _curControlBox.setPoint (i, newPoint.x () + 0.5, newPoint.y () + 0.5);
  }
}



void TransformTool::_updateMousePoint (const QPoint & point)
{
  if (_isTransformStart)
  {
    if (_isTranslateStart)
    {
      _doTranslate (point);
    }
    else if (_isRotateStart)
    {
      _doRotate (point);
    }
    else if (_isScaleStart)
    {
      _doScale (point);
    }
    _transformControlBox ();
  }
}



void TransformTool::_doTranslate (const QPoint & loc)
{
  _pAction->translate (_origTrans.translateVal + loc - _origMouseLoc);
}



void TransformTool::_doRotate (const QPoint & loc)
{
  QPoint center = _curControlBox.boundingRect ().center ();
  QPoint firstVector = _origMouseLoc - center;
  QPoint currentVector = loc - center;
  float startAngleR = atan ((double)firstVector.y () / firstVector.x ());
  if (firstVector.x () < 0)
    startAngleR += PI;
  float currentAngleR = atan ((double)currentVector.y () /currentVector.x ());
  if (currentVector.x () < 0)
    currentAngleR += PI;
  _pAction->rotate (_origTrans.rotateValR + currentAngleR - startAngleR);
}



void TransformTool::_doScale (const QPoint & loc)
{
  QPointF center = _curControlBox.boundingRect ().center ();
  QPointF xVector = _curControlBox.point (1) - _curControlBox.point (0);
  float xVectorLength = sqrt (pow (xVector.x (), 2) + pow (xVector.y (), 2));
  xVector /= xVectorLength;
  QPointF yVector = _curControlBox.point (3) - _curControlBox.point (0);
  float yVectorLength = sqrt (pow (yVector.x (), 2) + pow (yVector.y (), 2));
  yVector /= yVectorLength;
  QPointF firstVector = _origMouseLoc - center;
  QPointF currentVector = loc - center;
  float firstXLength = firstVector.x () * xVector.x ()
    + firstVector.y () * xVector.y ();
  float firstYLength = firstVector.x () * yVector.x ()
    + firstVector.y () * yVector.y ();
  float currentXLength = currentVector.x () * xVector.x ()
    + currentVector.y () * xVector.y ();
  float currentYLength = currentVector.x () * yVector.x ()
    + currentVector.y () * yVector.y ();
  float xScale = currentXLength / firstXLength;
  float yScale = currentYLength / firstYLength;
  _pAction->scale (QPointF (_origTrans.scaleVal.x () * xScale, 
    _origTrans.scaleVal.y () * yScale));
}



void TransformTool::_canvasPaintingEvent (QPainter & painter)
{
  if (_isTransformStart)
  {
    // Draw control box
    QPen painterPen;
    painterPen.setColor (QColor (100, 100, 100));
    painterPen.setStyle (Qt::SolidLine);
    painter.setPen (painterPen);
    
    painter.save ();
    painter.drawPolygon (_curControlBox);
    QRect cornerBox (-2, -2, 5, 5);
    for (int i = 0; i < _curControlBox.size (); ++i)
    {
      painter.save ();
      painter.translate ((_curControlBox.point (
        (i - 1 + _curControlBox.size ()) % _curControlBox.size ())
        + _curControlBox.point (i)) / 2);
      painter.rotate (_pAction->getTrans ().rotateValR * 180 / PI);
      painter.drawRect (cornerBox);
      painter.restore ();

      painter.save ();
      painter.translate (_curControlBox.point (i));
      painter.rotate (_pAction->getTrans ().rotateValR * 180 / PI);
      painter.drawRect (cornerBox);
      painter.restore ();
    }
    painter.restore ();
  }
}



void TransformTool::_canvasMousePressedEvent (QPoint loc, QMouseEvent * event)
{
  if (event->buttons () == Qt::LeftButton)
  {
    if (!_isTransformStart)
      throw ("transform is not started");
    if (_isTranslateStart || _isRotateStart || _isScaleStart)
      throw ("Some form of transform is in action.");

    _origTrans = _pAction->getTrans ();
    _origMouseLoc = loc;

    if (_curControlBox.containsPoint (loc, Qt::OddEvenFill))
      _isTranslateStart = true;
    else if (_isOnControlCorner (loc))
      _isScaleStart = true;
    else
      _isRotateStart = true;

    emit repaintViewport ();
  }
}

void TransformTool::_canvasMouseMovedEvent (QPoint loc, QMouseEvent * event)
{
  if (event->buttons () == Qt::LeftButton)
  {
    _updateMousePoint (loc);
    emit repaintViewport ();
  }
}

void TransformTool::_canvasMouseReleasedEvent (QPoint loc, QMouseEvent * event)
{
  if (event->buttons () == 0 && event->button () == Qt::LeftButton)
  {
    if (_isTranslateStart)
      _isTranslateStart = false;
    else if (_isRotateStart)
      _isRotateStart = false;
    else if (_isScaleStart)
      _isScaleStart = false;
    emit repaintViewport ();
  }
}



void TransformTool::_startEvent ()
{
  _startTransform ();
  emit repaintViewport ();
}



void TransformTool::_finishEvent ()
{
  _pAction->applyAction ();
  __pWork->getDoc ()->closePreview ();
  _isTransformStart = false;
  emit repaintViewport ();
}



bool TransformTool::_isOnControlCorner (const QPoint & point)
{
  for (int i = 0; i < _curControlBox.size (); ++i)
  {
    QPoint distance = point - _curControlBox.point (i);
    if (abs (distance.x ()) <= 3 && abs (distance.y ()) <= 3)
      return true;
  }
  return false;
}



// void TransformTool::_globalKeyPressedEvent (QKeyEvent * event)
// {
//   if (event->modifiers () & Qt::ControlModifier && event->key () == 'D')
//   {
//     _finishEvent ();
//   }
//   if (event->modifiers () == Qt::NoModifier)
//   {
//     if (event->key () == Qt::Key_Enter)
//     {
//       finishTransform ();
//     }
//     else if (event->key () == Qt::Key_Escape)
//     {
//       cancelTransform ();
//     }
//   }
// 
// }




